<template>
  <div class="table-pro">
    <!-- 表格组件 -->
    <el-table
      ref="tableRef"
      :data="data"
      :row-key="rowKey"
      v-bind="attrs"
      @header-contextmenu="handleCellContextMenu"
      :border="localConfig.showBorder"
      @header-dragend="handleHeaderDragend"
    >
      <slot></slot>
      <!-- 使用本地维护的 columns 副本 -->
      <template v-for="column in localConfig.visibleColumns" :key="column.prop || column.label">

        <lang-table-column
          v-if="column.prop && column.propEn"
          v-bind="{
      ...column,
      // 仅当 column.width 存在时，才添加 width 属性
      ...(column.width !== undefined && column.width !== null && { width: column.width })
    }"
          :align="localConfig.align"
          :header-align="localConfig.align">
          <!-- 表头插槽（如果列配置了slots.header） -->
          <template #header="scope" v-if="column.slots?.header">
            <!--            通过 scope.$index 判断表格行是否 “真实渲染”，从而避免了初始化阶段的无效渲染-->
            <slot
              v-if="scope.$index > -1"
              :name="column.slots.header"
              v-bind="scope"
            ></slot>
          </template>

          <!-- 单元格插槽（优先级：slots.default > 默认显示row[prop]） -->
          <template #default="scope">
            <template v-if="column.slots?.default">
              <!-- 渲染配置的默认插槽，并传递上下文 -->
              <slot
                v-if="scope.$index > -1"
                :name="column.slots.default"
                v-bind="scope"
              ></slot>
            </template>

          </template>
        </lang-table-column>
        <el-table-column
          v-else
          v-bind="{
      ...column,
      // 仅当 column.width 存在时，才添加 width 属性
      ...(column.width !== undefined && column.width !== null && { width: column.width })
    }"
          :align="localConfig.align"
          :header-align="localConfig.align">
          <!-- 表头插槽（如果列配置了slots.header） -->
          <template #header="scope" v-if="column.slots?.header">
            <!--            通过 scope.$index 判断表格行是否 “真实渲染”，从而避免了初始化阶段的无效渲染-->
            <slot
              v-if="scope.$index > -1"
              :name="column.slots.header"
              v-bind="scope"
            ></slot>
          </template>

          <!-- 单元格插槽（优先级：slots.default > 默认显示row[prop]） -->
          <template #default="scope">
            <template v-if="column.slots?.default">
              <!-- 渲染配置的默认插槽，并传递上下文 -->
              <slot
                v-if="scope.$index > -1"
                :name="column.slots.default"
                v-bind="scope"
              ></slot>
            </template>

          </template>
        </el-table-column>

      </template>
    </el-table>

    <!-- 右键菜单 -->
    <div
      v-if="contextMenuVisible"
      class="context-menu"
      :style="{ left: contextMenuLeft + 'px', top: contextMenuTop + 'px' }"
      @click.stop
      @mouseleave="handleMenuLeave"
    >
      <div class="menu-item" @click="openLayoutSetting">
        <el-icon class="menu-icon">
          <Setting/>
        </el-icon>
        <span>布局配置</span>
      </div>
      <div class="menu-item" @click="openExportSetting">
        <el-icon class="menu-icon">
          <Setting/>
        </el-icon>
        <span>导出为excel</span>
      </div>
    </div>

    <!-- 布局配置弹窗 -->
    <table-config
      v-model:visible="dialogVisible"
      v-model:config="localConfig"
      @update:config="handleConfigUpdate"
      :storageKey="storageKey"
    />
    <!-- 新增：使用独立导出组件 -->
    <table-export
      v-model:visible="exportVisible"
      :table-data="data"
      :table-instance="tableRef"
      :default-file-name="`数据`"
      :ignore-export-prop="localConfig.ignoreExportProp"
      :export-func-map="exportFuncMap"
    />

  </div>


</template>
<script setup lang="ts">
import {Setting} from '@element-plus/icons-vue'
import TableConfig from '@/components/TablePro/TableConfig.vue'
import {TableColumnCtx} from "element-plus";
import TableExport from '@/components/TablePro/TableExport.vue'
import {getField, TableConfigType} from "@/components/TablePro/data";
import {PropType, ref, useAttrs} from 'vue'
// 定义组件属性
const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  rowKey: {
    type: String,
    default: 'id'
  },
  config: {
    type: Object as PropType<TableConfigType>,
    default: () => ({
      showBorder: true // 是否显示边框
    })
  },
  storageKey: {
    type: String,
    required: true
  }
})

const localConfig = ref<TableConfigType>({
  ...props.config,
  showBorder: props.config.showBorder ? props.config.showBorder : true,
  align: props.config.align ? props.config.align : 'center',
  visibleColumns: props.config.columns
})
const exportFuncMap=ref(new Map())
// 初始化
onMounted(() => {
  loadConfigFromStorage()

  localConfig.value.visibleColumns?.forEach(column=>{
    if(column.exportFunc){
      exportFuncMap.value.set(getField(column.prop,column.propEn),column.exportFunc)
    }
  })

})

const {t} = useI18n()

/**
 * 处理一些默认值和多语言翻译
 */
const handleConfig = (): void => {

  localConfig.value.showBorder = props.config.showBorder ? props.config.showBorder : true
  localConfig.value.align = props.config.align ? props.config.align : 'center'
  localConfig.value.visibleColumns = props.config.columns

  localConfig.value.visibleColumns.forEach(column => {
    let value = column.label ? t(column.label) : null
    if (value) {
      column.label = value
    }
  })

}

/**
 * 从本地存储加载配置，没有则使用props传入的配置
 */
const loadConfigFromStorage = () => {
  try {
    // 1. 读取本地缓存
    const cacheKey = `TablePro.Layouts.${props.storageKey}`;
    const savedStr = localStorage.getItem(cacheKey);
    if (!savedStr) {
      localConfig.value = {...props.config}
    } else {
      // 2. 解析缓存
      const savedCache = JSON.parse(savedStr);

      // 3. 合并配置：核心保证“新列默认显示”
      localConfig.value = {
        ...props.config, // 新配置的基础字段（如边框、对齐）
        ...savedCache,  // 缓存的旧配置（如宽度、旧显示顺序）

        // 列配置：新列结构 + 旧宽度
        columns: props.config.columns.map(newCol => {
          // 1. 优先取缓存中的旧宽度（如果有），其次取新列配置的宽度
          const targetWidth = savedCache.columns?.find(old => old.prop === newCol.prop)?.width ?? newCol.width;

          // 2. 有宽度则添加 width 属性，无宽度则不添加
          return targetWidth
            ? {...newCol, width: targetWidth} // 有宽度：包含 width
            : {...newCol}; // 无宽度：不包含 width 属性
        }),

        // 显示列：旧显示列（补全新字段） + 新增的列（自动追加）
        visibleColumns: (() => {
          // 步骤1：处理缓存中的旧显示列（补全新字段和宽度）
          const oldVisibleColumns = savedCache.visibleColumns?.map(oldVisCol => {
            const newCol = props.config.columns.find(c => c.prop === oldVisCol.prop);
            return newCol ? {...newCol, width: oldVisCol.width} : null;
          }).filter(Boolean) || []; // 过滤缓存中已删除的列

          // 步骤2：找出新配置中“不在旧显示列”的新增列（需要默认显示）
          const newAddedColumns = props.config.columns.filter(newCol =>
            !oldVisibleColumns.some(visCol => visCol.prop === newCol.prop)
          );

          // 步骤3：合并（旧显示列保持原顺序 + 新增列追加到末尾）
          return [...oldVisibleColumns, ...newAddedColumns];
        })()
      };
    }

  } catch (error) {
    // 异常时：所有列默认显示
    console.error('缓存异常，重置为新配置（所有列默认显示）：', error);
    localConfig.value = {...props.config}
    localStorage.removeItem(`TablePro.Layouts.${props.storageKey}`);
  }

  handleConfig()
};
// 接收透传属性
const attrs = useAttrs()

// 右键菜单相关状态
const contextMenuVisible = ref(false)
const contextMenuLeft = ref(0)
const contextMenuTop = ref(0)
const dialogVisible = ref(false)

// 处理表头右键事件
const handleCellContextMenu = (_column: any, event: MouseEvent) => {
  // 阻止默认右键菜单
  event.preventDefault()
  event.stopPropagation()

  // 显示自定义右键菜单并定位
  contextMenuVisible.value = true
  contextMenuLeft.value = event.clientX
  contextMenuTop.value = event.clientY
}

// 点击空白处关闭右键菜单
document.addEventListener('click', () => {
  contextMenuVisible.value = false
})

// 鼠标离开菜单关闭
const handleMenuLeave = () => {
  contextMenuVisible.value = false
}

// 打开布局设置弹窗
const openLayoutSetting = () => {
  contextMenuVisible.value = false
  dialogVisible.value = true
}

const handleConfigUpdate = (newConfig: any) => {
  localConfig.value = {
    ...localConfig.value,
    ...newConfig,
    columns: props.config.columns // 保持所有列不变
  }
  // 同步到本地存储
  saveConfigToStorage()
}

// 封装：保存配置到本地存储
const saveConfigToStorage = () => {
  try {
    localStorage.setItem(
      `TablePro.Layouts.${props.storageKey}`,
      JSON.stringify(localConfig.value)
    )
  } catch (error) {
    console.error('Failed to save table config to localStorage:', error)
  }
}

// 新增：列宽调整结束时触发（核心逻辑）
const handleHeaderDragend = (newWidth: number, _oldWidth: number, column: TableColumnCtx) => {

  const visibleColumns = localConfig.value.visibleColumns
  if (!visibleColumns || visibleColumns.length < 1) {
    return;
  }

  // 1. 找到当前调整列在 visibleColumns 中的索引
  const visibleColumnIndex = visibleColumns.findIndex(
    col => col.prop === column.property
  )

  // 2. 更新该列的 width 属性（确保是数字类型，避免字符串导致的样式问题）
  if (visibleColumnIndex !== -1) {
    visibleColumns[visibleColumnIndex].width = newWidth
  }

  const columnIndex = localConfig.value.columns.findIndex(
    col => col.prop === column.property
  )
  if (columnIndex !== -1) {
    localConfig.value.columns[columnIndex].width = newWidth
  }
  saveConfigToStorage()
}

const tableRef = ref<any>(null) // el-table实例引用
const exportVisible = ref(false)
const openExportSetting = () => {
  contextMenuVisible.value = false
  exportVisible.value = true
}
</script>

<style scoped lang="scss">
.ym-table {
  position: relative;
}

// 自定义右键菜单样式
.context-menu {
  position: fixed;
  z-index: 1000;
  width: 150px;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border: 1px solid #e0e0e0;
  padding: 5px 0;
  overflow: hidden;

  .menu-item {
    display: flex;
    align-items: center;
    padding: 6px 16px;
    margin: 0 4px;
    border-radius: 4px;
    font-size: 14px;
    color: #333;
    cursor: pointer;
    transition: background-color 0.2s;

    &:hover {
      background-color: #f5f5f5;
    }

    .menu-icon {
      margin-right: 8px;
      vertical-align: middle
      //width: 16px;
      //height: 16px;
    }
  }
}

// 布局设置弹窗样式
.layout-setting {
  padding: 10px 0;

  h3 {
    margin-bottom: 16px;
    font-size: 16px;
    color: #333;
  }

  .el-checkbox-group {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;

    .el-checkbox {
      margin-right: 0;
    }
  }
}
</style>
